package com.tjetc.proxy;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.Socket;
import java.util.concurrent.TimeUnit;

public class ClientProxy {
    private static final int MAX_RETRIES = 3;
    private static final int RETRY_DELAY_MS = 1000;
    private static final String SERVER_HOST = "localhost";
    private static final int SERVER_PORT = 8888;

    /*
     * 返回某接口的代理对象
     * @param clz 某接口的类类型
     *
     * */
    public static <T> T getProxyInstance(Class<T> clz) {
        return (T) Proxy.newProxyInstance(clz.getClassLoader(), new Class[]{clz}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                int retries = 0;
                Exception lastException = null;

                while (retries < MAX_RETRIES) {
                    Socket socket = null;
                    ObjectInputStream in = null;
                    ObjectOutputStream out = null;

                    try {
                        socket = new Socket(SERVER_HOST, SERVER_PORT);
                        out = new ObjectOutputStream(socket.getOutputStream());
                        in = new ObjectInputStream(socket.getInputStream());

                        out.writeUTF(clz.getSimpleName());
                        out.writeUTF(method.getName());
                        out.writeObject(method.getParameterTypes());
                        out.writeObject(args);
                        out.flush();

                        Object result = in.readObject();
                        return result;

                    } catch (IOException e) {
                        lastException = e;
                        System.out.println("连接服务器失败，正在重试... (" + (retries + 1) + "/" + MAX_RETRIES + ")");
                        retries++;
                        
                        if (retries < MAX_RETRIES) {
                            try {
                                TimeUnit.MILLISECONDS.sleep(RETRY_DELAY_MS);
                            } catch (InterruptedException ie) {
                                Thread.currentThread().interrupt();
                                throw new RuntimeException("重试过程被中断", ie);
                            }
                        }
                    } catch (Exception e) {
                        throw new RuntimeException("调用远程方法时发生错误: " + e.getMessage(), e);
                    } finally {
                        closeQuietly(in);
                        closeQuietly(out);
                        closeQuietly(socket);
                    }
                }

                throw new RuntimeException("在" + MAX_RETRIES + "次尝试后仍然无法连接到服务器", lastException);
            }
        });
    }

    private static void closeQuietly(AutoCloseable resource) {
        if (resource != null) {
            try {
                resource.close();
            } catch (Exception e) {
                // 忽略关闭时的异常
            }
        }
    }
}
